import { isObject } from '..'  // npm i @jcstdio/jc-utils
import { Reactive, Ref } from './types';


const targetMap = new WeakMap();
let activeEffect: any = null;
function track(target: any, key: string | symbol) {
    // 获取target对象的依赖映射表
    let depsMap = targetMap.get(target);
     // 如果不存在，则创建一个新的映射表
    if (!depsMap) {
        depsMap = new Map();
        targetMap.set(target, depsMap);
    }
    // 获取key对应的依赖集合
    let dep = depsMap.get(key);
    // 如果不存在，则创建一个新的依赖集合
    if (!dep) {
        dep = new Set();
        depsMap.set(key, dep);
    }
    // 将当前的 activeEffect 添加到依赖集合中
    dep.add(activeEffect);
}

/**
 * 
 * @param target 
 * @param key 
 * @returns 
 */
function trigger(target: any, key: string | symbol, type:'ADD'|'SET'|'DELETE') {
    // 获取target对象的依赖映射表
    const depsMap = targetMap.get(target);
    // 如果不存在，则直接返回
    if (!depsMap) {
      return;
    }
    // 获取key对应的依赖集合
    const dep = depsMap.get(key);
    // 如果存在依赖集合，则遍历依赖集合中的所有effect函数并执行
    if (dep) {
      dep.forEach((effect: any) => {
        effect();
      });
    }
  }

/**
 * 将对象转换为响应式数据
 * @param obj 一个对象
 * @returns 对原对象 obj 的响应式代理。
 */
function reactive<T extends object>(obj: T): Reactive<T> {
    const observed = new Proxy(obj, {
        get(target: any, key: string | symbol, receiver: any) {

            // 在代理对象上模拟处一个 raw 的访问器属性，用于访问原始数据
            if(key==='raw'){
                return target
            }

            const result = Reflect.get(target, key, receiver);
            track(target, key);
            return isObject(result) ? reactive(result) : result;
        },
        set(target: any, key: string | symbol, value: any, receiver: any) {
            const oldValue = target[key];
            const result = Reflect.set(target, key, value, receiver);

            // target === receiver.raw 表面 receiver 就是 target 的代理对象
            if(target === receiver.raw) {
                // 比较新值旧值，不全等时才触发响应，但要注意 NaN !== NaN 这样的特例
                if (oldValue !== value && (oldValue===oldValue)||(value===value)) {
                    trigger(target, key, 'SET');
                }
            }
            return result;
        },
        deleteProperty(target, key){
            // 检查对象被操作的属性是否是对象自己的属性
            const hadKey = Object.prototype.hasOwnProperty.call(target, key);
            // 完成属性删除
            const result = Reflect.deleteProperty(target, key)

            if(result && hadKey){
                // 只有当被删除的属性是对象自己的属性并删除成功时，才触发更新
                trigger(target, key, 'DELETE')
            }
            return result
        }
    });
    return observed as Reactive<T>;
}

export {
//   reactive,
//   ref
}